home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Celestin Apprentice 5
/
Apprentice-Release5.iso
/
Source Code
/
Libraries
/
PlayerPRO 4.5.1
/
Plug-Ins
/
Import⁄Export Plugs
/
S3M2Mad.c
< prev
Wrap
Text File
|
1996-02-06
|
28KB
|
1,057 lines
/******************** ***********************/
//
// Player PRO 4.5x -- S3M to MADx
//
// Version 2.0 - 12.3.95 ANR
//
// To use with CodeWarrior 68K or PPC
//
// Antoine ROSSET
// 16 Tranchees
// 1206 GENEVA
// SWITZERLAND
//
// FAX: (+41 22) 346 11 97
// Compuserve: 100277,164
// Internet: rosset@dial.eunet.ch
//
/******************** ***********************/
#include "S3M.h"
#include "MAD.h"
#include "RDriver.h"
#if defined(powerc) || defined(__powerc)
enum {
PlayerPROPlug = kCStackBased
| RESULT_SIZE(SIZE_CODE(sizeof(OSErr)))
| STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof( OSType)))
| STACK_ROUTINE_PARAMETER(2, SIZE_CODE(sizeof( Ptr*)))
| STACK_ROUTINE_PARAMETER(3, SIZE_CODE(sizeof( MADPartition*)))
| STACK_ROUTINE_PARAMETER(4, SIZE_CODE(sizeof( PPInfoRec*)))
};
ProcInfoType __procinfo = PlayerPROPlug;
#else
#include <A4Stuff.h>
#endif
#define LOW(para) ((para) & 15)
#define HI(para) ((para) >> 4)
unsigned long Tdecode32( void *msg_buf)
{
unsigned char *buf = msg_buf;
return( (unsigned long) buf[3] << 24) | ( (unsigned long) buf[2] << 16) | ( (unsigned long) buf[ 1] << 8) | ( (unsigned long) buf[0]);
}
short Tdecode16( void *msg_buf)
{
unsigned char *buf = msg_buf;
return ( (short) buf[1] << 8) | ( (short) buf[0]);
}
Cmd* GetMADCommand( register short PosX, register short TrackIdX, register PatData* tempMusicPat)
{
if( PosX < 0) PosX = 0;
else if( PosX >= tempMusicPat->header.size) PosX = tempMusicPat->header.size -1;
return( & (tempMusicPat->Cmds[ (tempMusicPat->header.size * TrackIdX) + PosX]));
}
void pStrcpy(register unsigned char *s1, register unsigned char *s2)
{
register short len, i;
len = *s2;
for ( i = 0; i <= len; i++) s1[ i] = s2[ i];
}
void ConvertS3MEffect( Byte B0, Byte B1, Byte *Cmd, Byte *Arg)
{
Str255 tStr;
Byte LoB1 = LOW( B1);
Byte HiB1 = HI( B1);
switch( B0 + 0x40)
{
default: *Cmd = 0; *Arg = 0; break;
// Speed
case 'A': *Cmd = speedE; *Arg = B1; break;
// Tempo
case 'T': *Cmd = speedE; *Arg = B1; break;
case 'B': *Cmd = fastskipE; *Arg = B1; break;
case 'C': *Cmd = skipE; *Arg = B1; break;
case 'D':
if( LoB1 == 0 || HiB1 == 0) // Slide volume
{
*Cmd = slidevolE; *Arg = B1;
}
else if( HiB1 == 0x0F) // Fine Slide volume DOWN
{
*Cmd = extendedE;
*Arg = 11 << 4;
*Arg += LoB1;
}
else if( LoB1 == 0x0F) // Fine Slide volume UP
{
*Cmd = extendedE;
*Arg = 10 << 4;
*Arg += HiB1;
}
break;
case 'E':
if( HiB1 == 0x0F) // FineSlide DOWN
{
*Cmd = extendedE;
*Arg = 2 << 4; //not supported
*Arg += LoB1;
}
else if( HiB1 == 0x0E) // ExtraFineSlide DOWN
{
*Cmd = 0; *Arg = 0; //not supported
}
else // Slide DOWN
{
*Cmd = upslideE; *Arg = B1;
}
break;
case 'F':
if( HiB1 == 0x0F) // FineSlide UP
{
*Cmd = extendedE;
*Arg = 1 << 4; //not supported
*Arg += LoB1;
}
else if( HiB1 == 0x0E) // ExtraFineSlide UP
{
*Cmd = 0; *Arg = 0; //not supported
}
else // Slide UP
{
*Cmd = downslideE; *Arg = B1;
}
break;
case 'G': *Cmd = portamentoE; *Arg = B1; break;
case 'H': *Cmd = vibratoE; *Arg = B1; break;
case 'J': *Cmd = arpeggioE; *Arg = B1; break;
case 'K': *Cmd = vibratoslideE; *Arg = B1; break;
case 'L': *Cmd = portaslideE; *Arg = B1; break;
case 'O': *Cmd = offsetE; *Arg = B1; break;
case 'S': // Special Effects
switch( HiB1)
{
default: *Cmd = 0; *Arg = 0; break;
case 2: *Cmd = extendedE; *Arg = 5 << 4; *Arg += LoB1; break; // FineTune
case 3: *Cmd = extendedE; *Arg = 4 << 4; *Arg += LoB1; break; // Set Vibrato WaveForm
case 4: *Cmd = extendedE; *Arg = 7 << 4; *Arg += LoB1; break; // Set Tremolo WaveForm
case 0xB: *Cmd = extendedE; *Arg = 6 << 4; *Arg += LoB1; break; // Loop pattern
case 0xC: *Cmd = extendedE; *Arg = 12 << 4; *Arg += LoB1; break; // Cut sample
case 0xD: *Cmd = extendedE; *Arg = 13 << 4; *Arg += LoB1; break; // Delay sample
case 0xE: *Cmd = extendedE; *Arg = 14 << 4; *Arg += LoB1; break; // Delay pattern
}
break;
}
}
void ConvertMADEffect( Byte Cmd, Byte Arg, Byte *B0, Byte *B1)
{
*B0 = 0;
*B1 = 0;
switch( Cmd)
{
case speedE: *B0 = 'A' - 0x40; *B1 = Arg; break;
case fastskipE: *B0 = 'B' - 0x40; *B1 = Arg; break;
case skipE: *B0 = 'C' - 0x40; *B1 = Arg; break;
case slidevolE: *B0 = 'D' - 0x40; *B1 = Arg; break;
case upslideE: *B0 = 'E' - 0x40; *B1 = Arg; break;
case downslideE: *B0 = 'F' - 0x40; *B1 = Arg; break;
case portamentoE: *B0 = 'G' - 0x40; *B1 = Arg; break;
case vibratoE: *B0 = 'H' - 0x40; *B1 = Arg; break;
case arpeggioE: *B0 = 'J' - 0x40; *B1 = Arg; break;
case vibratoslideE: *B0 = 'K' - 0x40; *B1 = Arg; break;
case portaslideE: *B0 = 'L' - 0x40; *B1 = Arg; break;
case offsetE: *B0 = 'O' - 0x40; *B1 = Arg; break;
case extendedE:
switch( (Arg & 0xF0) >> 4)
{
case 1: *B0 = 'F' - 0x40; *B1 = 0xf0 + (Arg & 0x0F); break;
case 2: *B0 = 'E' - 0x40; *B1 = 0xf0 + (Arg & 0x0F); break;
case 5: *B0 = 'S' - 0x40; *B1 = 0x20 + (Arg & 0x0F); break;
case 4: *B0 = 'S' - 0x40; *B1 = 0x30 + (Arg & 0x0F); break;
case 7: *B0 = 'S' - 0x40; *B1 = 0x40 + (Arg & 0x0F); break;
case 6: *B0 = 'S' - 0x40; *B1 = 0xb0 + (Arg & 0x0F); break;
case 12: *B0 = 'S' - 0x40; *B1 = 0xc0 + (Arg & 0x0F); break;
case 13: *B0 = 'S' - 0x40; *B1 = 0xd0 + (Arg & 0x0F); break;
case 14: *B0 = 'S' - 0x40; *B1 = 0xe0 + (Arg & 0x0F); break;
case 11: *B0 = 'D' - 0x40; *B1 = 0xf0 + (Arg & 0x0F); break;
case 10: *B0 = 'D' - 0x40; *B1 = 0x0f + ((Arg & 0x0F)<<4); break;
}
break;
}
}
Ptr ConvertMad2S3M( MADPartition *theMAD)
{
short i, x, z, maxInstru;
Ptr finalS3M, finalS3MCopy, maxfinalS3M;
long InstruSize;
long NoIns;
long genHeaderSize;
s3minsform *ins[ 64];
Cmd *aCmd;
long PatternSize;
s3mform *s3minfo;
unsigned short *parapins;
unsigned short *parappat;
/********************************/
/* MAD INFORMATIONS */
/********************************/
InstruSize = 0;
PatternSize = 0;
NoIns = 0;
for( i = 0; i < 64 ; i++)
{
if( theMAD->header->fid[ i].numSamples > 0)
{
InstruSize += 16 + theMAD->sample[ i][ 0]->size;
//NoIns++;
NoIns = i+1;
}
}
for( i = 0; i < theMAD->header->numPat;i++)
{
PatternSize += 6L * theMAD->header->numChn * theMAD->partition[ i]->header.size;
PatternSize += 16;
}
/********************************/
finalS3MCopy = finalS3M = NewPtr( sizeof( s3mform) +
theMAD->header->numPointers +
NoIns*2 +
theMAD->header->numPat*2 +
sizeof(s3minsform) * NoIns +
InstruSize +
PatternSize);
maxfinalS3M = finalS3M + GetPtrSize( finalS3M);
if( finalS3M == 0L) return 0L;
/********************************/
/* s3minfo -- s3minfo -- s3minfo -- s3minfo -- */
/********************************/
{
s3minfo = (s3mform*) finalS3MCopy;
strncpy( s3minfo->name, theMAD->header->name, 28);
s3minfo->sig1 = 26;
s3minfo->type = 16;
s3minfo->sig2[ 0] = s3minfo->sig2[ 1] = 0;
s3minfo->ordernum = theMAD->header->numPointers; s3minfo->ordernum = Tdecode16( &s3minfo->ordernum);
s3minfo->insnum = NoIns; s3minfo->insnum = Tdecode16( &s3minfo->insnum);
s3minfo->patnum = theMAD->header->numPat; s3minfo->patnum = Tdecode16( &s3minfo->patnum);
s3minfo->flags = 0;
s3minfo->cwtv = 0x2013;
s3minfo->ffv = 1; s3minfo->ffv = Tdecode16( &s3minfo->ffv);
strncpy( s3minfo->s3msig, "SCRM", 4);
s3minfo->mastervol = 64;
s3minfo->initialspeed = theMAD->header->speed;
s3minfo->initialtempo = theMAD->header->tempo;
s3minfo->mastermul = 0x30;
for( i = 0; i < 12; i++) s3minfo->sig3[ i] = 0;
for( i = 0; i < 16; i++) s3minfo->chanset[ i] = i;
for( i = 16; i < 32; i++) s3minfo->chanset[ i] = 255;
finalS3MCopy += 96;
}
if( finalS3MCopy >= maxfinalS3M) Debugger();
/********************************/
/* orders -- orders -- orders -- orders */
/********************************/
{
unsigned char *orders;
orders = (unsigned char *) finalS3MCopy;
for( i = 0; i < theMAD->header->numPointers; i++)
{
orders[ i] = theMAD->header->oPointers[ i]; orders[ i] = Tdecode16( &orders[ i]);
}
finalS3MCopy += theMAD->header->numPointers;
}
if( finalS3MCopy >= maxfinalS3M) Debugger();
/********************************/
/* Ins Num -- Ins Num -- Ins Num -- Ins Num */
/********************************/
{
parapins = (unsigned short *) finalS3MCopy;
for( i = 0; i < NoIns; i++) parapins[ i] = 0;
finalS3MCopy += NoIns*2L;
}
if( finalS3MCopy >= maxfinalS3M) Debugger();
/********************************/
/* Pat Num -- Pat Num -- Pat Num -- Pat Num */
/********************************/
{
parappat = (unsigned short *) finalS3MCopy;
for( i = 0; i < theMAD->header->numPat; i++) parappat[ i] = 0;
finalS3MCopy += theMAD->header->numPat*2L;
}
if( finalS3MCopy >= maxfinalS3M) Debugger();
/*********************************/
/* Ins Form -- Ins Form -- Ins Form -- Ins Form */
/*********************************/
for (i = 0; i < NoIns; i++)
{
if( theMAD->header->fid[ i].numSamples > 0)
{
sData *curData = theMAD->sample[ i][ 0];
parapins[ i] = (16L + finalS3MCopy - finalS3M) / 16L;
finalS3MCopy = finalS3M + parapins[ i]*16L;
parapins[ i] = Tdecode16( ¶pins[ i]);
/**/
ins[ i] = (s3minsform*) finalS3MCopy;
ins[ i]->instype = 1;
strncpy( (Ptr) ins[ i]->insdosname, theMAD->header->fid[i].name, 12);
ins[ i]->inssig1 = 0;
ins[ i]->insmemseg = 0;
ins[ i]->inslength = curData->size; ins[ i]->inslength = Tdecode32( &ins[ i]->inslength);
ins[ i]->insloopbeg = curData->loopBeg; ins[ i]->insloopbeg = Tdecode32( &ins[ i]->insloopbeg);
ins[ i]->insloopend = curData->loopBeg + curData->loopSize; ins[ i]->insloopend = Tdecode32( &ins[ i]->insloopend);
ins[ i]->insvol = curData->vol;
ins[ i]->insdsk = 0;
ins[ i]->inspack = 0;
ins[ i]->insflags = 0;
if( curData->loopSize != 0) ins[ i]->insflags += 1;
if( curData->amp == 16) ins[ i]->insflags += 4;
ins[ i]->insloc2spd = curData->c2spd; ins[ i]->insloc2spd = Tdecode16( &ins[ i]->insloc2spd);
ins[ i]->inshic2spd = 0;
for( x = 0; x < 4; x++) ins[ i]->inssig2[ x] = 0;
ins[ i]->insgvspos = 256; ins[ i]->insgvspos = Tdecode16( &ins[ i]->insgvspos);
ins[ i]->insint512 = 0; ins[ i]->insint512 = Tdecode16( &ins[ i]->insint512);
ins[ i]->insintlastused = 0;
strncpy( (Ptr) ins[ i]->insname, theMAD->header->fid[i].name, 28);
ins[ i]->inssig = 'SCRS';
}
else
{
parapins[ i] = (16L + finalS3MCopy - finalS3M) / 16L;
finalS3MCopy = finalS3M + parapins[ i]*16L;
parapins[ i] = Tdecode16( ¶pins[ i]);
/**/
ins[ i] = (s3minsform*) finalS3MCopy;
ins[ i]->instype = 0;
strncpy( (Ptr) ins[ i]->insdosname, theMAD->header->fid[i].name, 12);
ins[ i]->inssig1 = 0;
ins[ i]->insmemseg = 0;
ins[ i]->inslength = 0;
ins[ i]->insloopbeg = 0;
ins[ i]->insloopend = 0;
ins[ i]->insvol = 0;
ins[ i]->insdsk = 0;
ins[ i]->inspack = 0;
ins[ i]->insflags = 0;
ins[ i]->insloc2spd = NOFINETUNE; ins[ i]->insloc2spd = Tdecode16( &ins[ i]->insloc2spd);
ins[ i]->inshic2spd = 0;
for( x = 0; x < 4; x++) ins[ i]->inssig2[ x] = 0;
ins[ i]->insgvspos = 256;
ins[ i]->insint512 = 0;
ins[ i]->insintlastused = 0;
strncpy( (Ptr) ins[ i]->insname, theMAD->header->fid[i].name, 28);
ins[ i]->inssig = 0;
}
/**/
finalS3MCopy += sizeof(s3minsform);
}
if( finalS3MCopy >= maxfinalS3M) Debugger();
/*********************************/
/* Sample Data -- Sample Data -- Sample Data */
/*********************************/
for (i = 0; i < NoIns; i++)
{
if( theMAD->header->fid[ i].numSamples > 0)
{
sData *curData = theMAD->sample[ i][ 0];
ins[ i]->insmemseg = (16L + finalS3MCopy - finalS3M) / 16L;
finalS3MCopy = finalS3M + ins[ i]->insmemseg*16L;
ins[ i]->insmemseg = Tdecode16( &ins[ i]->insmemseg);
BlockMove( curData->data, finalS3MCopy, curData->size);
finalS3MCopy += curData->size;
}
}
if( finalS3MCopy >= maxfinalS3M) Debugger();
/*********************************/
/* Pattern Data -- Pattern Data -- Pattern Data */
/*********************************/
for (i = 0; i < theMAD->header->numPat; i++)
{
long Row = 0;
parappat[ i] = (16L + finalS3MCopy - finalS3M) / 16L;
finalS3MCopy = finalS3M + parappat[ i]*16L;
parappat[ i] = Tdecode16( ¶ppat[ i]);
finalS3MCopy++;
while( Row < 64)
{
for( z = 0; z < theMAD->header->numChn; z++)
{
Byte *tempChar = (Byte*) finalS3MCopy;
aCmd = GetMADCommand( Row, z, theMAD->partition[ i]);
if( aCmd->note != 0xFF ||
aCmd->ins != 0 ||
aCmd->cmd != 0 ||
aCmd->arg != 0 ||
aCmd->vol != 0xFF)
{
*tempChar = 0;
finalS3MCopy++;
// Channel
*tempChar = z;
// PERIOD
if( aCmd->note != 0xFF || aCmd->ins != 0)
{
short Octave, Note;
*tempChar += 32;
if( aCmd->note == 0xFF)
{
finalS3MCopy[ 0] = 0xFF;
}
else
{
Octave = aCmd->note / 12;
Note = aCmd->note - Octave*12;
finalS3MCopy[ 0] = Octave << 4;
finalS3MCopy[ 0] += Note;
}
finalS3MCopy[ 1] = aCmd->ins;
finalS3MCopy += 2L;
}
// VOLUME
if( aCmd->vol != 0xFF || aCmd->cmd == volumeE)
{
*tempChar += 64;
if( aCmd->cmd == volumeE) finalS3MCopy[ 0] = aCmd->arg;
else finalS3MCopy[ 0] = aCmd->vol - 0x10;
finalS3MCopy += 1L;
}
// PARAMETER
if( aCmd->cmd != 0 || aCmd->arg != 0)
{
*tempChar += 128;
ConvertMADEffect( aCmd->cmd, aCmd->arg, (Byte*) &finalS3MCopy[ 0], (Byte*) &finalS3MCopy[ 1]);
finalS3MCopy += 2L;
}
}
}
*finalS3MCopy = 0; // end of row
finalS3MCopy++;
Row++;
}
if( finalS3MCopy >= maxfinalS3M) Debugger();
}
SetPtrSize( finalS3M, finalS3MCopy - finalS3M);
return( (Ptr) finalS3M);
}
OSErr ConvertS3M2Mad( Ptr theS3M, long MODSize, MADPartition *theMAD)
{
long i, PatMax, x, z, channel, Row;
long sndSize, OffSetToSample, OldTicks, temp, starting;
Ptr MaxPtr;
OSErr theErr;
Ptr theInstrument[ 64], destPtr;
Byte tempChar, *theS3MCopy;
short Note, Octave, maxTrack;
short S3Mperiod[ 12] = {1712,1616,1524,1440,1356,1280,1208,1140,1076,1016, 960, 907};
long note_st3period;
long note_amigaperiod;
Byte *ChannelSettings;
/**** Variables pour le MAD ****/
Cmd *aCmd;
/**** Variables pour le S3M ****/
s3mform s3minfo;
/********************************/
for( i = 0 ; i < 64; i ++)
{
theInstrument[ i] = 0L;
}
/**** Header principal *****/
theS3MCopy = (Byte*) theS3M;
BlockMove( theS3MCopy, &s3minfo, 96);
theS3MCopy += 96;
s3minfo.ordernum = Tdecode16( &s3minfo.ordernum);
s3minfo.insnum = Tdecode16( &s3minfo.insnum);
s3minfo.patnum = Tdecode16( &s3minfo.patnum);
s3minfo.flags = Tdecode16( &s3minfo.flags);
s3minfo.cwtv = Tdecode16( &s3minfo.cwtv);
s3minfo.ffv = Tdecode16( &s3minfo.ffv);
/**** Order Num *****/
s3minfo.orders = (unsigned char *) NewPtr( s3minfo.ordernum);
BlockMove( theS3MCopy, s3minfo.orders, s3minfo.ordernum);
theS3MCopy += s3minfo.ordernum;
/**** Ins Num *****/
s3minfo.parapins = (unsigned short *) NewPtr( s3minfo.insnum * 2L);
BlockMove( theS3MCopy, s3minfo.parapins, s3minfo.insnum * 2L);
theS3MCopy += s3minfo.insnum * 2L;
for( i = 0; i < s3minfo.insnum; i++)
{
s3minfo.parapins[ i] = Tdecode16( &s3minfo.parapins[ i]);
}
/**** Pat Num *****/
s3minfo.parappat = (unsigned short *) NewPtr( s3minfo.patnum * 2L);
BlockMove( theS3MCopy, s3minfo.parappat, s3minfo.patnum * 2L);
theS3MCopy += s3minfo.patnum * 2L;
for( i = 0; i < s3minfo.patnum; i++)
{
s3minfo.parappat[ i] = Tdecode16( &s3minfo.parappat[ i]);
}
/**** Ins Data ****/
if( s3minfo.insnum > 64) s3minfo.insnum = 64;
s3minfo.insdata = (s3minsform *) NewPtr( sizeof(s3minsform) * s3minfo.insnum);
for (i = 0; i < s3minfo.insnum; i++)
{
theInstrument[ i] = 0L;
theS3MCopy = (Byte*) theS3M;
theS3MCopy += s3minfo.parapins[i]*16L;
BlockMove( theS3MCopy, &s3minfo.insdata[i], sizeof(s3minsform));
s3minfo.insdata[i].insmemseg = Tdecode16( &s3minfo.insdata[i].insmemseg);
s3minfo.insdata[i].inslength = Tdecode32( &s3minfo.insdata[i].inslength);
if( s3minfo.insdata[i].insflags&1)
{
s3minfo.insdata[i].insloopbeg = Tdecode32( &s3minfo.insdata[i].insloopbeg);
s3minfo.insdata[i].insloopend = Tdecode32( &s3minfo.insdata[i].insloopend);
}
else
{
s3minfo.insdata[i].insloopbeg = 0;
s3minfo.insdata[i].insloopend = 0;
}
s3minfo.insdata[i].insloc2spd = Tdecode16( &s3minfo.insdata[i].insloc2spd);
s3minfo.insdata[i].inshic2spd = Tdecode16( &s3minfo.insdata[i].inshic2spd);
s3minfo.insdata[i].insgvspos = Tdecode16( &s3minfo.insdata[i].insgvspos);
s3minfo.insdata[i].insint512 = Tdecode16( &s3minfo.insdata[i].insint512);
s3minfo.insdata[i].insintlastused = Tdecode32( &s3minfo.insdata[i].insintlastused);
if (s3minfo.insdata[i].instype == 1 && s3minfo.insdata[i].inspack == 0 && s3minfo.insdata[i].inssig == 'SCRS')
{
theS3MCopy = (Byte*) theS3M;
theS3MCopy += s3minfo.insdata[i].insmemseg*16L;
theInstrument[ i] = (Ptr) theS3MCopy;
}
else
{
theInstrument[ i] = 0L;
}
}
/******** Le S3M a été lu et analysé ***********/
/******** Copie des informations dans le MAD ***/
theMAD->header = (MADSpec*) NewPtrClear( sizeof( MADSpec));
theMAD->header->MAD = 'MADH';
for(i=0; i<32; i++) theMAD->header->name[i] = 0;
for(i=0; i<28; i++) theMAD->header->name[i] = s3minfo.name[i];
theMAD->header->numPat = s3minfo.patnum;
theMAD->header->numPointers = s3minfo.ordernum;
theMAD->header->speed = s3minfo.initialspeed;
theMAD->header->tempo = s3minfo.initialtempo;
for(i=0; i<128; i++) theMAD->header->oPointers[ i] = 0;
for(i=0; i<s3minfo.ordernum; i++)
{
theMAD->header->oPointers[ i] = s3minfo.orders[i];
if( theMAD->header->oPointers[ i] < 0 || theMAD->header->oPointers[ i] >= s3minfo.patnum) theMAD->header->oPointers[ i] = 0;
}
/********************/
/***** INSTRUMENTS *****/
/********************/
for(i = 0 ; i < MAXINSTRU; i++)
{
for( x = 0; x < MAXSAMPLE; x++) theMAD->sample[ i][ x] = 0L;
theMAD->header->fid[i].numSamples = 0;
}
for(i=0; i<s3minfo.insnum; i++)
{
InstrData *curIns = &theMAD->header->fid[ i];
curIns->type = 0;
if( theInstrument[ i] != 0L)
{
sData *curData;
curIns->numSamples = 1;
curData = theMAD->sample[ i][ 0] = (sData*) NewPtrClear( sizeof( sData));
curData->size = s3minfo.insdata[i].inslength;
curData->loopBeg = s3minfo.insdata[i].insloopbeg;
curData->loopSize = s3minfo.insdata[i].insloopend - s3minfo.insdata[i].insloopbeg;
curData->vol = s3minfo.insdata[i].insvol;
curData->c2spd = s3minfo.insdata[i].insloc2spd;
curData->loopType = 0;
curData->amp = 8; if( s3minfo.insdata[i].insflags&4) curData->amp = 16;
curData->panning = 0;
curData->relNote = 0;
for( x = 0; x < 28; x++) curData->name[ x] = s3minfo.insdata[i].insname[x];
curData->data = NewPtr( curData->size);
if( curData->data == 0L) DebugStr("\pInstruments: I NEED MEMORY !!! NOW !");
if( curData->data != 0L)
{
BlockMove( theInstrument[i], curData->data, curData->size);
if( s3minfo.ffv != 1)
{
for( temp = 0; temp < curData->size; temp++) *(curData->data + temp) -= 0x80;
}
}
}
else curIns->numSamples = 0;
}
/********************/
/*********************/
/* Check MaxTrack */
/*********************/
maxTrack = 0;
for( i = 0; i < theMAD->header->numPat ; i++)
{
Row = 0;
if( s3minfo.parappat[ i] > 0)
{
theS3MCopy = (Byte*) theS3M;
theS3MCopy += ( (long) s3minfo.parappat[i] )*16L;
theS3MCopy++;
while( Row < 64)
{
tempChar = *theS3MCopy;
theS3MCopy++;
if( tempChar == 0) Row++;
else
{ // Channel
channel = tempChar;
channel &= 31;
if( channel > maxTrack) maxTrack = channel;
if( (tempChar & 32) != 0) theS3MCopy += 2L;
if( (tempChar & 64) != 0) theS3MCopy += 1L;
if( (tempChar & 128) != 0) theS3MCopy += 2L;
}
}
}
}
maxTrack ++;
/** Pair **/
maxTrack++;
maxTrack /= 2;
maxTrack *= 2;
/********************/
/***** TEMPORAIRE ******/
/********************/
theMAD->header->numChn = maxTrack;
starting = 0;
for( i = 0; i < MAXPATTERN; i++) theMAD->partition[ i] = 0L;
for( i = 0; i < theMAD->header->numPat ; i++)
{
theMAD->partition[ i] = (PatData*) NewPtrClear( sizeof( PatData) + theMAD->header->numChn * 64L * sizeof( Cmd));
if( theMAD->partition[ i] == 0L) return MADNeedMemory;
theMAD->partition[ i]->header.size = 64L;
theMAD->partition[ i]->header.compMode = 'NONE';
for( x = 0; x < 20; x++) theMAD->partition[ i]->header.name[ x] = 0;
theMAD->partition[ i]->header.patBytes = 0L;
theMAD->partition[ i]->header.unused2 = 0L;
MaxPtr = (Ptr) theMAD->partition[ i];
MaxPtr += sizeof( PatData) + theMAD->header->numChn * 64L * sizeof( Cmd);
for( Row = 0; Row < 64; Row++)
{
for(z = 0; z < theMAD->header->numChn; z++)
{
aCmd = GetMADCommand( Row, z, theMAD->partition[ i]);
aCmd->note = 0xFF;
aCmd->ins = 0;
aCmd->cmd = 0;
aCmd->arg = 0;
aCmd->vol = 0xFF;
}
}
if( s3minfo.parappat[ i] > 0)
{
theS3MCopy = (Byte*) theS3M;
theS3MCopy += ( (long) s3minfo.parappat[i] )*16L;
theS3MCopy++;
Row = 0;
while( Row < 64)
{
/*
BYTE:flag, 0 = end of row
&31 = channel
&32 = follows; BYTE:note, BYTE:instrument
&64 = follows; BYTE:volume
&128 = follows; BYTE:command, BYTE:info
*/
tempChar = *theS3MCopy;
theS3MCopy++;
if( tempChar == 0) Row++;
else
{
// Channel
channel = tempChar;
channel &= 31;
if( channel >= 0 && channel < theMAD->header->numChn) z = channel;
else DebugStr("\pOut - Channel");
aCmd = GetMADCommand( Row, z, theMAD->partition[ i]);
// PERIOD
if( (tempChar & 32) != 0)
{
aCmd->note = theS3MCopy[ 0];
Octave = (aCmd->note & 0xF0) >> 4;
Note = (aCmd->note & 0x0F);
aCmd->note = Octave*12 + Note;
if( aCmd->note < 0 || aCmd->note >= NUMBER_NOTES) aCmd->note = 0xFF;
aCmd->ins = theS3MCopy[ 1];
// if( theMAD->instrument[ theS3MCopy[ 1] - 1] != 0) aCmd->InstrumentNo = theS3MCopy[ 1];
theS3MCopy += 2L;
}
// VOLUME
if( (tempChar & 64) != 0)
{
aCmd->vol = theS3MCopy[ 0];
if( aCmd->vol > 64) aCmd->vol = 64;
aCmd->vol += 0x10;
theS3MCopy += 1L;
}
else aCmd->vol = 255;
// PARAMETER
if( (tempChar & 128) != 0)
{
if( theS3MCopy[ 0] != 255)
{
ConvertS3MEffect( theS3MCopy[ 0], theS3MCopy[ 1], &aCmd->cmd, &aCmd->arg);
}
theS3MCopy += 2L;
}
}
}
}
}
DisposPtr( (Ptr) s3minfo.orders); DisposPtr( (Ptr) s3minfo.parapins);
DisposPtr( (Ptr) s3minfo.parappat); DisposPtr( (Ptr) s3minfo.insdata);
return noErr;
}
OSErr ExtractS3MInfo( PPInfoRec *info, Ptr AlienFile)
{
s3mform *myS3M = ( s3mform*) AlienFile;
short i;
short maxInstru;
short tracksNo;
s3mform s3minfo;
/********************************/
/**** Header principal *****/
BlockMove( AlienFile, &s3minfo, 96);
/*** Signature ***/
info->signature = 'S3M ';
/*** Internal name ***/
myS3M->name[ 27] = '\0';
pStrcpy( info->internalFileName, CtoPstr( myS3M->name));
/*** Total Patterns ***/
info->totalPatterns = 0;
/*** Partition Length ***/
info->partitionLength = 0;
/*** Total Instruments ***/
info->totalInstruments = Tdecode16( &s3minfo.insnum);
pStrcpy( info->formatDescription, "\pS3M Plug");
return noErr;
}
OSErr TestS3MFile( Ptr AlienFile)
{
s3mform *myS3M = ( s3mform*) AlienFile;
if( myS3M->s3msig[ 0] == 'S' &&
myS3M->s3msig[ 1] == 'C' &&
myS3M->s3msig[ 2] == 'R' &&
myS3M->s3msig[ 3] == 'M') return noErr;
else return MADFileNotSupportedByThisPlug;
}
OSErr main( OSType order, FSSpec *AlienFileFSSpec, MADPartition *MadFile, PPInfoRec *info)
{
OSErr myErr;
Ptr AlienFile;
short vRefNum, iFileRefI;
long dirID, sndSize;
#ifndef powerc
long oldA4 = SetCurrentA4(); //this call is necessary for strings in 68k code resources
#endif
HGetVol( 0L, &vRefNum, &dirID);
HSetVol( 0L, AlienFileFSSpec->vRefNum, AlienFileFSSpec->parID);
myErr = noErr;
switch( order)
{
case 'EXPL':
AlienFile = ConvertMad2S3M( MadFile);
if( AlienFile != 0L)
{
myErr = FSOpen( AlienFileFSSpec->name, 0, &iFileRefI);
if( myErr == fnfErr)
{
myErr = Create( AlienFileFSSpec->name, 0, 'SNPL', 'S3M ');
myErr = FSOpen( AlienFileFSSpec->name, 0, &iFileRefI);
}
if( myErr == noErr)
{
FInfo fndrInfo;
sndSize = GetPtrSize( AlienFile);
myErr = SetEOF( iFileRefI, sndSize);
myErr = FSWrite( iFileRefI, &sndSize, AlienFile);
FSClose( iFileRefI);
GetFInfo( AlienFileFSSpec->name, 0, &fndrInfo);
fndrInfo.fdCreator = 'SNPL';
fndrInfo.fdType = 'S3M ';
SetFInfo( AlienFileFSSpec->name, 0, &fndrInfo);
}
DisposPtr( AlienFile); AlienFile = 0L;
}
else myErr = MADNeedMemory;
break;
case 'IMPL':
myErr = FSOpen( AlienFileFSSpec->name, 0, &iFileRefI);
if( myErr == noErr)
{
GetEOF( iFileRefI, &sndSize);
// ** MEMORY Test Start
AlienFile = NewPtr( sndSize * 2L);
if( AlienFile == 0L) myErr = MADNeedMemory;
// ** MEMORY Test End
else
{
DisposPtr( AlienFile);
AlienFile = NewPtr( sndSize);
myErr = FSRead( iFileRefI, &sndSize, AlienFile);
if( myErr == noErr)
{
myErr = TestS3MFile( AlienFile);
if( myErr == noErr)
{
myErr = ConvertS3M2Mad( AlienFile, GetPtrSize( AlienFile), MadFile);
}
}
DisposPtr( AlienFile); AlienFile = 0L;
}
FSClose( iFileRefI);
}
break;
case 'TEST':
myErr = FSOpen( AlienFileFSSpec->name, 0, &iFileRefI);
if( myErr == noErr)
{
sndSize = 1024L;
AlienFile = NewPtr( sndSize);
if( AlienFile == 0L) myErr = MADNeedMemory;
else
{
myErr = FSRead( iFileRefI, &sndSize, AlienFile);
myErr = TestS3MFile( AlienFile);
DisposPtr( AlienFile); AlienFile = 0L;
}
FSClose( iFileRefI);
}
break;
case 'INFO':
myErr = FSOpen( AlienFileFSSpec->name, 0, &iFileRefI);
if( myErr == noErr)
{
GetEOF( iFileRefI, &info->fileSize);
sndSize = 5000L; // Read only 5000 first bytes for optimisation
AlienFile = NewPtr( sndSize);
if( AlienFile == 0L) myErr = MADNeedMemory;
else
{
myErr = FSRead( iFileRefI, &sndSize, AlienFile);
if( myErr == noErr)
{
myErr = ExtractS3MInfo( info, AlienFile);
}
DisposPtr( AlienFile); AlienFile = 0L;
}
FSClose( iFileRefI);
}
break;
default:
myErr = MADOrderNotImplemented;
break;
}
HSetVol( 0L, vRefNum, dirID);
#ifndef powerc
SetA4( oldA4);
#endif
return myErr;
}